package chair;

/**
 * Le Striatum donne la parole à intervalle régulier aux fonctions de
 * l'organisme
 * 
 * @author nomhad
 * 
 */

final class Striatum extends Thread {
	/** FIXME: structure extensible ou lever erreur si plein */
	private static final int MAX_LISTENER_CALLERS = 7;
	/** Les fonctions reliées au striatum */
	private Function[] listFunctions;
	/** Nombre de fonctions actuellement en écoute */
	private int numFunctionCaller = 0;

	Striatum() {
		super("Striatum");
		listFunctions = new Function[MAX_LISTENER_CALLERS];
	}

	/**
	 * Quand le moment est opportun Brain lance le thread
	 */
	void init() {
		synchronized (this) {
			if (!isAlive()) {
				setDaemon(true);
				// setPriority(Thread.MAX_PRIORITY);
				start();
			}
		}
	}

	/**
	 * Ajoute une fonction de l'organisme à faire tourner
	 * 
	 * @param fct
	 *            Function à ajouter
	 */
	synchronized void add(Function fct) {
		int i;
		for (i = 0; i < numFunctionCaller; i++)
			if (listFunctions[i] == fct)
				break;
		// FunctionCaller existe pas déjà : on ajoute
		if (i == numFunctionCaller) {
			listFunctions[numFunctionCaller++] = fct;
		}
	}

	/**
	 * Le Striatum se charge d'ajouter un réflexe dans la file de sa fonction
	 * 
	 * @param ref
	 * @param impulse
	 *            impulsion à envoyer à ce réflexe
	 */
	synchronized void addReflexe(Reflex ref, Impulse impulse) {
		// Oh punaise que c'est alambiqué ! J'ai créé un monstre !
		// ...finalement à force de le voir tous les jours je l'ai adopté.
		ref.getFunction().addReflex(ref, impulse);
	}

	/**
	 * Si réflexe prédictif sera traité différemment par fonction
	 * 
	 * @param ref
	 * @param impulse
	 *            impulsion à envoyer à ce réflexe
	 */
	synchronized void addResponse(Reflex ref, Impulse impulse) {
		ref.getFunction().addResponse(ref, impulse);
	}

	@Override
	public void run() {
		// singleton.setPriority(Thread.MAX_PRIORITY);
		for (;;) {

			// Run events at normal priority so they can use Thread.yield()
			// FIXME: repense prio, surtout sur nxt
			// singleton.setPriority(Thread.NORM_PRIORITY);

			// On fait tourner toutes les fonctions
			for (int i = 0; i < numFunctionCaller; i++)
				listFunctions[i].tick();

			// Avant de calmer le jeu entre deux interros des fonctions on
			// montre quand même qu'il faura pas nous laisser poireauter
			// singleton.setPriority(Thread.MAX_PRIORITY);

			synchronized (this) {
				try {
					wait(Chronos.getSriatumPollingTime());
				} catch (InterruptedException e) {
				}

			}

		}
	}
}
